package controls.instructions {
	import events.ExperimentEvent;
	
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import mx.containers.VBox;
	import mx.controls.Alert;
	import mx.controls.Button;
	import mx.controls.Label;
	import mx.controls.Text;
	import mx.events.FlexEvent;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.HTTPService;
	
	/**
	 * A class to manage instructions for an experiment.
	 * @author Brent Kersanske
	 */ 
	public class InstructionsControlClass extends VBox {
		
		[Bindable]
		public var instructionsService:HTTPService;
		
		[Bindable]
		public var highLevelVBox:VBox;
		
		[Bindable]
		public var trialVBox:VBox;
		
		[Bindable]
		public var readyButton:Button;
		
		[Bindable]
		public var countDownLabel:Label;
			
		private var _readyButtonText:String;
		
		private var _instructionsFile:String;
		
		private var _instructionsTitle:String;
		
		/* The minimum time in seconds that is required for reading of the instructions before moving forward.*/
		private var _minTimeToReadInstructions:Number = 0;

		[Bindable]
		public function set readyButtonText(buttonText:String):void {
			_readyButtonText = buttonText;	
		}
		
		public function get readyButtonText():String {
			return _readyButtonText;
		}
		
		[Bindable]
		public function set instructionsFile(file:String):void {
			_instructionsFile = file;
		}
		
		public function get instructionsFile():String {
			return _instructionsFile;
		}
		
		[Bindable]
		public function set instructionsTitle(title:String):void {
			_instructionsTitle = title;
		}
		
		public function get instructionsTitle():String {
			return _instructionsTitle;
		}
		
		[Bindable]
		public function set minTimeToReadInstructions(minTime:Number):void {
			_minTimeToReadInstructions = minTime;
		}
		
		public function get minTimeToReadInstructions():Number {
			return _minTimeToReadInstructions;
		}
		
		public function InstructionsControlClass() {
			addEventListener(FlexEvent.CREATION_COMPLETE, handleCreationComplete);
		}

		/**
		 * Function called after all flex components have been created.
		 */ 
		private function handleCreationComplete(e:FlexEvent):void {
			loadInstructions();
		}
		
		/**
		 * Load the instructions!
		 */ 
		private function loadInstructions():void {
			this.instructionsService.url = this.instructionsFile;
			this.instructionsService.send();
		}
		
		/**
		 * 
		 */ 		
		public function handleHTTPServiceFault(event:FaultEvent):void {
			Alert.show(event.fault.faultString);
		}
		
		public function handleInstructionsResult(event:ResultEvent):void {
			var instructions:XML 			  = XML(event.result);
			var highLevelInstructions:XMLList = instructions.highLevel.instruction;
			var trialInstructions:XMLList     = instructions.trial.step;
			for each(var highLevel:XML in highLevelInstructions) {
				addHighLevelInstructionLine(highLevel.@value);
			}
			for each(var trialInstruction:XML in trialInstructions) {
				addTrialInstructionLine(trialInstruction.@value);
			}
			startReadingTimer();
		}
		
		/**
		 * Adds a line to the high level instruction box.
		 */ 
		private function addHighLevelInstructionLine(highLevel:String):void {
			var highLevelInstructionLine:Text  = new Text();
			highLevelInstructionLine.text 	   = highLevel;
			highLevelInstructionLine.styleName = "highLevelInstruction";
			this.highLevelVBox.addChild(highLevelInstructionLine);
		}
				
		/**
		 * Adds a line to the trial instruction box.
		 */ 
		private function addTrialInstructionLine(trialInstruction:String):void {
			var trialInstructionLine:Text  = new Text();
			trialInstructionLine.text 	   = trialInstruction;
			trialInstructionLine.styleName = "trialInstruction";  
			this.trialVBox.addChild(trialInstructionLine);
		}
		
		/**
		 * Starts the reading timer if a minimum read time has been set.
		 * Otherwise, just enables the ready button for user interaction.
		 */ 
		private function startReadingTimer():void {
			if(this.minTimeToReadInstructions > 0) {
				this.countDownLabel.text = String(this.minTimeToReadInstructions);
				var readingTimer:Timer   = new Timer(1000, this.minTimeToReadInstructions);
				readingTimer.addEventListener(TimerEvent.TIMER, handleReadingTimerTick);
				readingTimer.addEventListener(TimerEvent.TIMER_COMPLETE, handleReadingTimerComplete);
				readingTimer.start();
			} else {
				this.readyButton.enabled = true;
			}
		}
		
		private function handleReadingTimerTick(e:TimerEvent):void {
			this.countDownLabel.text = String(Number(this.countDownLabel.text) - 1);
		}
		
		/**
		 * When the timer has completed
		 */ 
		private function handleReadingTimerComplete(e:TimerEvent):void {
			this.readyButton.enabled = true;
			this.countDownLabel.text = "";
		}
		
		/**
		 * Event signal that user has finished reading the instructions.
		 */ 
		public function signalReadiness(e:Event):void {
			dispatchEvent(new ExperimentEvent(ExperimentEvent.INSTRUCTIONS_COMPLETE, true, false));
		}
	}
}